#include <stdio.h>
#include "crtSerial_C.h"
#include "crtSerial.h"
#include <iostream>
#include <string.h>
#include <string>
#include <unistd.h>

crtSerial::crtSerial(const std::string& com, int baudrate, int databits, int stopbits, int parity)
{
    int fd = open_dev(com.data());
    
    if ( fd == -1) {
        std::cerr << "Error: Failed to open serial port " << com << ". Exiting program." << std::endl;
        std::exit(EXIT_FAILURE);
    }
    if (set_baudrate(fd, baudrate) == -1) {
        std::cerr << "Error: Failed to set baudrate " << baudrate << ". Exiting program." << std::endl;
        std::exit(EXIT_FAILURE);
    }
    if (set_other_param(fd, databits, stopbits, parity) == -1) {
        std::cerr << "Error: Failed to set serial port parameters (databits: " << databits 
                  << ", stopbits: " << stopbits << ", parity: " << parity 
                  << ") for port " << com << ". Exiting program." << std::endl;
        std::exit(EXIT_FAILURE);
    }

    this->fd = fd;
}

crtSerial::~crtSerial()
{
    this->close();
}


void crtSerial::close()
{
    if (close_dev(this->fd) == -1) {
        std::cerr << "Error: Failed to close. Exiting program." << std::endl;
        std::exit(EXIT_FAILURE);
    }
}

void crtSerial::write(char* str)
{
    if (write_dev(this->fd, str, strlen(str)) == -1) {
        std::cerr << "Error: Failed to write. Exiting program." << std::endl;
        std::exit(EXIT_FAILURE);
    }
}

void crtSerial::write(std::string str)
{
    const char* charPtr = str.c_str();
    if (write_dev(this->fd, const_cast<char*>(charPtr), strlen(charPtr)) == -1) {
        std::cerr << "Error: Failed to write. Exiting program." << std::endl;
        std::exit(EXIT_FAILURE);
    }
}


std::string crtSerial::read(int count)
{
    if (count >= 1000 || count <= 0) {
        std::cerr << "serial read error" << std::endl;
        return ""; 
    }

    char buf[1000];

    if (read_dev(this->fd, buf, count) == -1) {
        std::cerr << "serial read error" << std::endl;
        std::exit(EXIT_FAILURE);
    }

    return std::string(buf, count);
}

std::string crtSerial::read_line()
{
    char buf[1000];
    int index = 0;
    char ch;

    while (true) {
        if (this->in_waitting()) {
            if (read_dev(this->fd, &ch, 1) == -1) {
                std::cerr << "serial read error" << std::endl;
                std::exit(EXIT_FAILURE);
            }


            buf[index] = ch;
            index++;

            if (ch == '\n' || index >= sizeof(buf) - 1) {
                buf[index] = '\0';
                break;
            }
            if (ch == '\r' || index >= sizeof(buf) - 1) {
                buf[index] = '\0';
                break;
            }
        }
    }
    return std::string(buf);
}


int crtSerial::in_waitting(int timeout)
{
    int res = check_dev(this->fd, 0);
    if (res == -1) {
        std::cerr << "serial check error" << "endl";
        std::exit(EXIT_FAILURE);
    }
    return res;
}


